package com.yugao.fintech.draper.auth.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yugao.fintech.draper.datasource.entity.PageResult;
import com.yugao.fintech.draper.core.model.ResultVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@RequestMapping("/token")
@RestController
public class TokenEndpoint {
    @Autowired
    private OAuth2AuthorizationService oAuth2AuthorizationService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 退出登录
     */
    @DeleteMapping("/logout")
    public ResultVO<Void> logout(HttpServletRequest request,
                                 @RequestHeader(value = HttpHeaders.AUTHORIZATION) String authorization) {
        String token = authorization.replace(OAuth2AccessToken.TokenType.BEARER.getValue(), StrUtil.EMPTY).trim();
        log.info("退出登录,token:{}", token);
        return removeToken(token);
    }

    /**
     * 删除token
     */
    @SneakyThrows
    @DeleteMapping("/{token}")
    public ResultVO<Void> removeToken(@PathVariable("token") String token) {
        OAuth2Authorization authorization = oAuth2AuthorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN);
        oAuth2AuthorizationService.remove(authorization);
        return ResultVO.success();
    }

    /**
     * 分页查询token
     *
     * @param param 分页参数
     * @return
     */
    @PostMapping("/page")
    public ResultVO<PageResult> pageQuery(@RequestBody Map<String, Object> param) {
        redisTemplate.setValueSerializer(RedisSerializer.java());
        String key = "token::access_token::*";
        Set<String> keys = redisTemplate.keys(key);
        Integer current = MapUtil.getInt(param, "current");
        Integer size = MapUtil.getInt(param, "size");
        List<String> pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList());
        List<Map> list = redisTemplate.opsForValue().multiGet(pages).stream().map(o -> {
            OAuth2Authorization authorization = (OAuth2Authorization) o;
            HashMap<String, Object> map = new HashMap<>();
            // 客户端
            map.put("client_id", authorization.getRegisteredClientId());
            // 用户名
            map.put("username", authorization.getPrincipalName());
            // token值
            OAuth2Authorization.Token<OAuth2AccessToken> accessToken = authorization.getAccessToken();
            map.put("access_token", accessToken.getToken().getTokenValue());
            // 过期时间
            String expiresAt = TemporalAccessorUtil.format(accessToken.getToken().getExpiresAt(),
                    DatePattern.NORM_DATETIME_PATTERN);
            map.put("expires_in", expiresAt);
            // token类型
            map.put("token_type", "access_token");
            return map;
        }).collect(Collectors.toList());

        Page page = new Page(current, size);
        page.setRecords(list);
        page.setTotal(keys.size());
        return ResultVO.success(PageResult.success(page));
    }
}
